<?php

namespace App\Console\Commands;

use App\Models\Call;
use App\Models\Queue;
use App\Models\Sip;
use App\Models\Task;
use App\Service\CallcenterListenAleg;
use App\Service\CallcenterListenBleg;
use App\Service\CallcenterListenQueue;
use App\Service\SwooleFreeswitch;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;

class SwooleCallcenterRun extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'swoole:callcenter:run';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = '群呼运行';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        $redis_key = config('freeswitch.redis_key.callcenter_task');
        Redis::del($redis_key);
        //服务启动或重启时检测是否有已启动的任务
        $res = Task::query()->where(['status'=>2])->select(['id'])->get();
        if ($res->isNotEmpty()) {
            foreach ($res as $key => $task) {
                Redis::rPush($redis_key,$task->id);
            }
        }
        \Swoole\Coroutine\run(function () use ($redis_key) {
            //启动服务
            while (true) {
                $task_id = Redis::lPop($redis_key);
                if ($task_id == null) {
                    sleep(10);
                    continue;
                }
                \Swoole\Coroutine::create(function () use ($task_id){

                    $fs = new SwooleFreeswitch();
                    if (!$fs->connect()) {
                        Task::query()->where('id',$task_id)->update(['status' => 1]);
                        return false;
                    }

                    while (true){
                        $task = Task::with(['gateway'])
                            ->where('status',2)
                            ->where('id',$task_id)
                            ->first();

                        //检测是否有启动的任务
                        if ($task == null ){
                            break;
                        }

                        //检测执行日期
                        $now_date = strtotime(date('Y-m-d'));
                        if ( $now_date < strtotime($task->date_start) || $now_date > strtotime($task->date_end) ) {
                            //延迟10秒
                            sleep(10);
                            continue;
                        }

                        //检测执行时间
                        $now_time = strtotime(date('H:i:s'));
                        if ( $now_time < strtotime($task->time_start) || $now_time > strtotime($task->time_end) ) {
                            //延迟10秒
                            sleep(10);
                            Log::info("任务：".$task->name."运行时间不满足");
                            continue;
                        }

                        //检测网关信息
                        if ($task->gateway==null){
                            Log::info("任务：".$task->name." 的网关不存在，任务停止");
                            $task->update(['status'=>1]);
                            break;
                        }

                        //检测队列是否有坐席
                        if ($task->sips == null){
                            Log::info("任务：".$task->name." 无坐席存在，任务停止");
                            $task->update(['status'=>1]);
                            break;
                        }

                        //只要有坐席空闲就进行呼叫
                        $sips = Sip::query()
                            ->whereIn('username',explode(',',$task->sips))
                            ->where('status',1)
                            ->where('state','down')
                            ->get();
                        if ($sips->count() === 0){
                            Log::info("任务：".$task->name." 无空闲坐席，sleep：1秒");
                            sleep(1);
                            continue;
                        }

                        // 队列中等待电话数
                        $wait = $fs->api('fifo count '.$task->id);
                        if (trim($wait) == 'none'){
                            Log::info("任务：".$task->name." 的队列配置错误");
                            $task->update(['status' => 1]);
                            break;
                        }

                        $arr = explode(':',trim($wait));
                        if ($arr[2] >= $sips->count()){
                            sleep(2);
                            continue;
                        }

                        $channel = floor(($sips->count() - $arr[2]) * $task->channel);

                        if ($channel <= 0) {
                            Log::info("任务ID：".$task->name." 的并发".$channel."不需要呼叫");
                            sleep(10);
                            continue;
                        }

                        //进行呼叫
                        $calls = Call::query()
                            ->where('task_id',$task->id)
                            ->where('status',1)
                            ->orderBy('id','asc')
                            ->take($channel)
                            ->get();
                        if ($calls->isEmpty()){
                            Log::info("任务：".$task->name."已完成");
                            $task->update(['status'=>3]);
                            break;
                        }
                        foreach ($calls as $call){
                            $uuid = uuid_generate();
                            $call->update([
                                'status'=>2,
                                'aleg_uuid'=>$uuid,
                                'datetime_originate_phone'=>date('Y-m-d H:i:s')
                            ]);
                            Log::info("更新号码: ".$call->phone." 状态为：2");
                            $phone = $task->gateway->prefix ? $task->gateway->prefix.$call->phone : $call->phone;
                            $varStr  = "{origination_uuid=".$uuid."}";
                            $varStr .= "{ignore_early_media=true}";
                            if ($task->gateway->outbound_caller_id){
                                $varStr .= "{origination_caller_id_number=".$task->gateway->outbound_caller_id."}";
                                $varStr .= "{origination_caller_id_name=".$task->gateway->outbound_caller_id."}";
                            }
                            $dailStr = "originate ".$varStr."sofia/gateway/gw".$task->gateway_id."/".$phone." fifo_in_".$task->id.")";
                            Log::info("呼叫：".$dailStr);
                            $fs->bgapi($dailStr);
                            sleep(2);
                        }
                        sleep(6);
                    }
                });

            }
        });
    }
}
